package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.constants.article.HotArticleConstants;
import com.heima.common.exception.CustomException;
import com.heima.feigns.UserFeign;
import com.heima.model.comment.dtos.CommentDTO;
import com.heima.model.comment.dtos.CommentLikeDTO;
import com.heima.model.comment.dtos.CommentSaveDTO;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.mess.UpdateArticleMess;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Autowired
    UserFeign userFeign;
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    CommentHotService commentHotService;
    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     *      添加评论
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment( CommentSaveDTO dto) {
        //1. 校验参数
        if (dto == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        //        校验是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //校验文章id   校验内容不为空  校验内容长度不能大于140个字符 (validated校验)
        if (dto.getArticleId() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2. 阿里云校验评论内容是否违规
        log.info("阿里云文本审核开始===========");

        log.info("阿里云文本审核结束===========");
//
       //简单:  此步不做      普通: 阿里云检测有问题提示      高级:  有问题不报异常，替换为**)
//
        //3. 远程查询当前登陆用户信息
        ResponseResult<ApUser> apUserResponseResult = userFeign.findUserById(user.getId());
        if (!apUserResponseResult.checkCode()) {
            throw new CustomException(AppHttpCodeEnum.REMOTE_SERVER_ERROR);
        }
        ApUser apUser = apUserResponseResult.getData();
        String apUserName = apUser.getName();
//
        //4. 创建评论信息，并保存到mongo
        ApComment apComment = new ApComment();
//        BeanUtils.copyProperties(apComment,apUser);

        apComment.setAuthorId(apUser.getId());
        apComment.setAuthorName(apUserName);
        apComment.setArticleId(dto.getArticleId());
        apComment.setType((short)0);
        apComment.setContent(dto.getContent());

        //  频道信息暂未实现
        apComment.setChannelId(null);

        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag((short)0);
        apComment.setLatitude(null);
        apComment.setLongitude(null);
        apComment.setAddress(null);
        apComment.setOrd(null);
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());

        ApComment comment = mongoTemplate.insert(apComment);
        System.out.println(dto.getContent());

        // =======================新加代码==========================
        UpdateArticleMess mess = new UpdateArticleMess();
        mess.setType(UpdateArticleMess.UpdateArticleType.COMMENT);
        mess.setArticleId(dto.getArticleId());
        mess.setAdd(1);
        rabbitTemplate.convertAndSend(HotArticleConstants.HOT_ARTICLE_SCORE_BEHAVIOR_QUEUE, JSON.toJSONString(mess));
        log.info("评论行为 发送消息 ==>{}",mess);
        // =======================新加代码==========================
        return ResponseResult.okResult();
    }

    /**
     *      评论点赞
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDTO dto) {
        //1. 参数校验
        if (dto == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        //  校验是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
        }

        //评论id不能为空  operation必须为 0  或  1
        //2. 根据评论id查询评论数据， 为返回错误信息
        Query query = Query.query(Criteria.where("id").is(dto.getCommentId()));
        ApComment apComment = mongoTemplate.findOne(query, ApComment.class);
        if (apComment == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST,"没有这个评论");
        }
        //3. 如果是点赞操作 判断是否已经点赞
        Integer likes ;
        //获取用户ID
        Integer userId = AppThreadLocalUtils.getUser().getId();
        if (dto.getOperation() == 0) {
            query = Query.query(Criteria.where("authorId").is(userId).and("commentId").is(dto.getCommentId()));
            ApCommentLike one = mongoTemplate.findOne(query, ApCommentLike.class);
            if (one == null) {
                //未点过赞   保存点赞信息到mongo
                ApCommentLike apCommentLike = new ApCommentLike();
                apCommentLike.setCommentId(dto.getCommentId());
                apCommentLike.setAuthorId(userId);
                mongoTemplate.insert(apCommentLike);
                //并修改评论信息的点赞数量( + 1)
                query = Query.query(Criteria.where("id").is(dto.getCommentId()));
                apComment = mongoTemplate.findOne(query, ApComment.class);
                likes = apComment.getLikes()+1;
                apComment.setLikes(likes);
                mongoTemplate.save(apComment);
                if (apComment.getLikes() >= 10 && apComment.getFlag().shortValue() == 0) {
                    commentHotService.hotCommentExecutor(apComment);
                }
                HashMap<String, Integer> map = new HashMap<>();
                map.put("likes",likes);
                return ResponseResult.okResult(map);
            }
            //点过赞提示 请勿重复点赞
            throw new CustomException(AppHttpCodeEnum.DATA_EXIST,"已经点赞过");
        }
        //4. 如果是取消点赞操作
        query = Query.query(Criteria.where("authorId").is(userId).and("commentId").is(dto.getCommentId()));
        ApCommentLike one = mongoTemplate.findOne(query, ApCommentLike.class);

        if (one == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST,"没有点赞过");
        }
        //删除点赞信息
        mongoTemplate.remove(one);
        //并修改评论信息的点赞数量( - 1) , 要判断下别减成负数
        query = Query.query(Criteria.where("id").is(dto.getCommentId()));
        apComment = mongoTemplate.findOne(query, ApComment.class);
        likes = apComment.getLikes()-1<0?0:apComment.getLikes()-1;
        apComment.setLikes(likes);
        mongoTemplate.save(apComment);
//
        //5. 返回结果时，需要返回点赞点赞数量  返回的key要求必须是:  likes
        HashMap<String, Integer> map = new HashMap<>();
        map.put("likes",likes);
        return ResponseResult.okResult(map);

    }
    /**
     * 根据 文章id 查询评论列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findByArticleId(CommentDTO dto) {
        //1. 校验参数
        if (dto == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        //校验文章id   校验内容不为空  校验内容长度不能大于140个字符 (validated校验)
        if (dto.getArticleId() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2. 根据条件查询评论列表
        List<ApComment> apCommentList;
        Date date =dto.getMinDate();

        Integer pageSize = dto.getSize();
        if (pageSize == null) {
            pageSize=10;
        }
        Query query;

        if (dto.getIndex().intValue() == 1) {
            //  新的列表
            query = Query.query(Criteria.where("articleId").is(dto.getArticleId())
                    .and("flag").is(1))
                    .with(Sort.by(Sort.Direction.DESC, "likes"));
            apCommentList = mongoTemplate.find(query, ApComment.class);
            // 热点集合不为空
            if (CollectionUtils.isNotEmpty(apCommentList)) {
                pageSize = pageSize -apCommentList.size();
                List<ApComment> normalCommentList = mongoTemplate.find(getQuery(dto, pageSize), ApComment.class);
                apCommentList.addAll(normalCommentList);
            }else {
                apCommentList = mongoTemplate.find(getQuery(dto, pageSize), ApComment.class);

            }
        }else {
            apCommentList = mongoTemplate.find(getQuery(dto, pageSize), ApComment.class);
        }

        //3. 判断当前用户是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user.getId()==0) {
            //4. 如果未登录直接返回评论列表
            return ResponseResult.okResult(apCommentList);
        }
//        //5. 如果登录了 需要检查在当前评论列表中 哪些评论登陆人点赞过
//
        List<ApCommentVo> apCommentVos = new ArrayList<>();

        //        (将所有ApComment 转成 ApCommentVO , 点过赞的operation设置为0)
        //获取用户所有的评论点赞
        query = Query.query(Criteria.where("authorId").is(user.getId()));
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(query, ApCommentLike.class);

        for (ApComment apComment : apCommentList) {
            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtils.copyProperties(apComment,apCommentVo);
            for (ApCommentLike apCommentLike : apCommentLikes) {
                //如果评论列表中的  评论id   和  用户的评论列表点赞中的  评论id  进行对比
                if (apComment.getId().equals(apCommentLike.getCommentId())) {
                    apCommentVo.setOperation((short)0);
                }
            }
            apCommentVos.add(apCommentVo);
        }

        return ResponseResult.okResult(apCommentVos);

    }

    /**
     *  获得普通评论数据
     * @param dto
     * @param size
     * @return
     */
    private Query getQuery(CommentDTO dto, Integer size) {
        return Query.query(Criteria.where("articleId").is(dto.getArticleId())
                .and("flag").is(0).and("createdTime").lt(dto.getMinDate()))
                .limit(size).with(Sort.by(Sort.Direction.DESC, "createdTime"));
    }
}
